/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.rbac.service.secret.impl;

import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.context.GlobalExtendedContext;
import com.je.common.base.mapper.query.Query;
import com.je.common.base.service.MetaService;
import com.je.common.base.util.SystemSecretUtil;
import com.je.common.base.util.TreeUtil;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.model.dd.DictionaryItemVo;
import com.je.meta.rpc.dictionary.DictionaryItemRpcService;
import com.je.meta.rpc.dictionary.DictionaryRpcService;
import com.je.meta.rpc.func.MetaFuncRpcService;
import com.je.rbac.cache.SecretSettingCache;
import com.je.rbac.service.secret.SecretSettingService;
import org.apache.servicecomb.provider.pojo.RpcReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.je.common.base.util.SystemSecretUtil.*;

@Service
public class SecretSettingServiceImpl implements SecretSettingService {

    private static final String DEFAULT_SECRET_CODE = "10";
    private static final String DEFAULT_SECRET_NAME = "公开";

    @Autowired
    private MetaService metaService;
    @Autowired
    private SecretSettingCache secretSettingCache;
    @Autowired
    private DictionaryRpcService dictionaryRpcService;
    @Autowired
    private MetaFuncRpcService metaFuncRpcService;

    @Override
    public void initSecretContext(DynaBean secretSettingBean) {
        if (!"1".equals(secretSettingBean.getStr("SYSSECRET_OPEN_CODE"))) {
            clearSecretContext();
            return;
        }
        Map<String, String> settingMap = new HashMap<>();
        settingMap.put(SECRET_SWITCH_KEY, "1");
        settingMap.put(SECRET_CODE_KEY, secretSettingBean.getStr("SYSSECRET_SYS_CODE"));
        settingMap.put(SECRET_CODE_NAME, secretSettingBean.getStr("SYSSECRET_SYS_NAME"));
        secretSettingCache.putMapCache(settingMap);
        GlobalExtendedContext.putAll(settingMap);
        metaFuncRpcService.enableFormField("JE_RBAC_VDEPTUSER","SY_SECRET_CODE");
    }

    @Override
    public void clearSecretContext() {
        secretSettingCache.removeCache(SECRET_SWITCH_KEY);
        secretSettingCache.removeCache(SECRET_CODE_KEY);
        secretSettingCache.removeCache(SECRET_CODE_NAME);
        GlobalExtendedContext.removeContext(SECRET_SWITCH_KEY, SECRET_CODE_KEY, SECRET_CODE_NAME);
        metaFuncRpcService.disableFormField("JE_RBAC_VDEPTUSER","SY_SECRET_CODE");
    }

    @Override
    public Map<String, String> requireSystemSecretInfo() {
        List<DynaBean> settingBeanList = metaService.select("JE_RBAC_SYSSECRET", ConditionsWrapper.builder().orderByDesc("SY_CREATETIME"));
        if (settingBeanList == null) {
            return new HashMap<>();
        }
        Map<String, String> result = new HashMap<>();
        result.put("switch", settingBeanList.get(0).getStr("SYSSECRET_OPEN_CODE"));
        result.put("systemSecretCode", settingBeanList.get(0).getStr("SYSSECRET_SYS_CODE"));
        result.put("systemSecretName", settingBeanList.get(0).getStr("SYSSECRET_SYS_NAME"));
        return result;
    }

    @Override
    public Map<String, String> requireUserContextSecretInfo(String ip, String accountId) {
        String machineSecretCode = DEFAULT_SECRET_CODE;
        String machineSecretName = DEFAULT_SECRET_NAME;
        String accountSecretCode = DEFAULT_SECRET_CODE;
        String accountSecretName = DEFAULT_SECRET_NAME;

        List<DynaBean> machineSecretBeanList = metaService.select("JE_RBAC_MACSECRET", ConditionsWrapper.builder().eq("MACSECRET_MAC_IP", ip));
        DynaBean accountBean = metaService.selectOneByPk("JE_RBAC_ACCOUNT", accountId);
        if (accountBean != null && !Strings.isNullOrEmpty(accountBean.getStr("SY_SECRET_CODE"))) {
            accountSecretCode = accountBean.getStr("SY_SECRET_CODE");
            accountSecretName = accountBean.getStr("SY_SECRET_NAME");
        }

        if (machineSecretBeanList != null && !machineSecretBeanList.isEmpty()) {
            machineSecretCode = machineSecretBeanList.get(0).getStr("MACSECRET_LEVEL_CODE");
            machineSecretName = machineSecretBeanList.get(0).getStr("MACSECRET_LEVEL_NAME");
        }

        //查找默认规则
        DynaBean relationRuleBean = metaService.selectOne("JE_RBAC_CONTEXTSECRET", ConditionsWrapper.builder()
                .eq("CONTEXTSECRET_DEFAULT_CODE", "1").eq("CONTEXTSECRET_TYPE", "USERCONTEXT"));
        if (relationRuleBean == null) {
            if (Integer.valueOf(machineSecretCode) < Integer.valueOf(accountSecretCode)) {
                buildUserContext(accountId, machineSecretCode, machineSecretName);
                return buildUserContextSecretResult(accountId, machineSecretCode, machineSecretName);
            } else {
                buildUserContext(accountId, accountSecretCode, accountSecretName);
                return buildUserContextSecretResult(accountId, accountSecretCode, accountSecretName);
            }
        }

        //查找规则明细
        List<DynaBean> relationInfoBeanList = metaService.select("JE_RBAC_CONTEXTDEFINE", ConditionsWrapper.builder()
                .eq("JE_RBAC_CONTEXTSECRET_ID", relationRuleBean.getStr("JE_RBAC_CONTEXTSECRET_ID"))
                .eq("CONTEXTDEFINE_USERSECRET_CODE", accountSecretCode)
                .like("CONTEXTDEFINE_MACSECRET_CODE", machineSecretCode));
        if (relationInfoBeanList == null || relationInfoBeanList.isEmpty()) {
            if (Integer.valueOf(machineSecretCode) < Integer.valueOf(accountSecretCode)) {
                buildUserContext(accountId, machineSecretCode, machineSecretName);
                return buildUserContextSecretResult(accountId, machineSecretCode, machineSecretName);
            } else {
                buildUserContext(accountId, accountSecretCode, accountSecretName);
                return buildUserContextSecretResult(accountId, accountSecretCode, accountSecretName);
            }
        }

        Integer secretCode = null;
        for (DynaBean eachRelationInfoBean : relationInfoBeanList) {
            if (secretCode == null) {
                secretCode = eachRelationInfoBean.getInt("CONTEXTDEFINE_CONTEXTSECRET_CODE");
                continue;
            }
            if (eachRelationInfoBean.getInt("CONTEXTDEFINE_CONTEXTSECRET_CODE") > secretCode) {
                secretCode = eachRelationInfoBean.getInt("CONTEXTDEFINE_CONTEXTSECRET_CODE");
                continue;
            }
        }
        String secretName = findUserSecretName(String.valueOf(secretCode));
        buildUserContext(accountId, String.valueOf(secretCode), secretName);
        return buildUserContextSecretResult(accountId, String.valueOf(secretCode), secretName);
    }

    private String findSystemSecretName(String secretCode) {
        List<DictionaryItemVo> itemVoList = dictionaryRpcService.getDicList("JE_RBAC_SYSSECRET", new Query(), false);
        for (DictionaryItemVo eachNode : itemVoList) {
            if (secretCode.equals(eachNode.getCode())) {
                return eachNode.getText();
            }
        }
        return null;
    }

    private String findUserSecretName(String secretCode) {
        List<DictionaryItemVo> itemVoList = dictionaryRpcService.getDicList("JE_RBAC_USERSECRET", new Query(), false);
        for (DictionaryItemVo eachNode : itemVoList) {
            if (secretCode.equals(eachNode.getCode())) {
                return eachNode.getText();
            }
        }
        return null;
    }

    @Override
    public JSONTreeNode requireSystemFuncSecretInfo(String relation) {
        JSONTreeNode rootNode = TreeUtil.buildRootNode();
        String systemSecretCode = secretSettingCache.getCacheValue(SECRET_CODE_KEY);
        if (Strings.isNullOrEmpty(systemSecretCode)) {
            return rootNode;
        }

        ConditionsWrapper wrapper = ConditionsWrapper.builder().eq("CONTEXTSECRET_TYPE", "SYSFUNC");
        if (Strings.isNullOrEmpty(relation)) {
            wrapper.eq("CONTEXTSECRET_DEFAULT_CODE", "1");
        } else {
            wrapper.eq("CONTEXTSECRET_CODE", relation);
        }

        DynaBean systemFuncRelationBean = metaService.selectOne("JE_RBAC_CONTEXTSECRET", wrapper);
        if (systemFuncRelationBean == null) {
            return null;
        }

        List<DynaBean> systemFuncRelationInfoList = metaService.select("JE_RBAC_SYSFUNCSECRET", ConditionsWrapper.builder()
                .eq("JE_RBAC_CONTEXTSECRET_ID", systemFuncRelationBean.getStr("JE_RBAC_CONTEXTSECRET_ID"))
                .eq("SYSFUNCSECRET_SYSSECRET_CODE", systemSecretCode));
        if (systemFuncRelationInfoList == null || systemFuncRelationInfoList.isEmpty()) {
            return null;
        }

        List<String> codeList = Splitter.on(",").splitToList(systemFuncRelationInfoList.get(0).getStr("SYSFUNCSECRET_FUNCSECRET_CODE"));
        List<String> nameList = Splitter.on(",").splitToList(systemFuncRelationInfoList.get(0).getStr("SYSFUNCSECRET_FUNCSECRET_NAME"));

        JSONTreeNode eachNode;
        for (int i = 0; i < codeList.size(); i++) {
            eachNode = new JSONTreeNode();
            eachNode.setId(codeList.get(i));
            eachNode.setCode(codeList.get(i));
            eachNode.setText(nameList.get(i));
            eachNode.setParent(rootNode.getId());
            eachNode.setNodeType("LEAF");
            eachNode.setLeaf(true);
            eachNode.setLayer("1");
            rootNode.getChildren().add(eachNode);
        }

        return rootNode;
    }

    @Override
    public JSONTreeNode requireFuncFormSecretInfo(String funcId) {
        JSONTreeNode rootNode = TreeUtil.buildRootNode();

        String relation = null;
        String funcSecretCode;
        DynaBean funcSecretBean = metaService.selectOne("JE_RBAC_FUNCSECRET", ConditionsWrapper.builder().eq("JE_CORE_FUNCINFO_ID", funcId));
        if (funcSecretBean != null) {
            relation = funcSecretBean.getStr("FUNCSECRET_RELATION_CODE");
            funcSecretCode = funcSecretBean.getStr("FUNCSECRET_SECRET_CODE");
        } else {
            funcSecretCode = "10";
        }

        ConditionsWrapper wrapper = ConditionsWrapper.builder().eq("CONTEXTSECRET_TYPE", "FUNCFORM");
        if (Strings.isNullOrEmpty(relation)) {
            wrapper.eq("CONTEXTSECRET_DEFAULT_CODE", "1");
        } else {
            wrapper.eq("CONTEXTSECRET_CODE", relation);
        }

        DynaBean funcFormRelationBean = metaService.selectOne("JE_RBAC_CONTEXTSECRET", wrapper);
        if (funcFormRelationBean == null) {
            return null;
        }

        List<DynaBean> funcFormRelationInfoList = metaService.select("JE_RBAC_FUNCFORMSECRET", ConditionsWrapper.builder()
                .eq("JE_RBAC_CONTEXTSECRET_ID", funcFormRelationBean.getStr("JE_RBAC_CONTEXTSECRET_ID"))
                .eq("FUNCFORMSECRET_FUNCSECRET_CODE", funcSecretCode));
        if (funcFormRelationInfoList == null || funcFormRelationInfoList.isEmpty()) {
            return null;
        }

        List<String> codeList = Splitter.on(",").splitToList(funcFormRelationInfoList.get(0).getStr("FUNCFORMSECRET_FORMSECRET_CODE"));
        List<String> nameList = Splitter.on(",").splitToList(funcFormRelationInfoList.get(0).getStr("FUNCFORMSECRET_FORMSECRET_NAME"));

        JSONTreeNode eachNode;
        for (int i = 0; i < codeList.size(); i++) {
            eachNode = new JSONTreeNode();
            eachNode.setId(codeList.get(i));
            eachNode.setCode(codeList.get(i));
            eachNode.setText(nameList.get(i));
            eachNode.setParent(rootNode.getId());
            eachNode.setNodeType("LEAF");
            eachNode.setLeaf(true);
            eachNode.setLayer("1");
            rootNode.getChildren().add(eachNode);
        }
        return rootNode;
    }

    @Override
    public JSONTreeNode requireSystemFlowSecretInfo(String relation) {
        JSONTreeNode rootNode = TreeUtil.buildRootNode();
        String systemSecretCode = secretSettingCache.getCacheValue(SECRET_CODE_KEY);
        if (Strings.isNullOrEmpty(systemSecretCode)) {
            return rootNode;
        }

        ConditionsWrapper wrapper = ConditionsWrapper.builder().eq("CONTEXTSECRET_TYPE", "SYSFLOW");
        if (Strings.isNullOrEmpty(relation)) {
            wrapper.eq("CONTEXTSECRET_DEFAULT_CODE", "1");
        } else {
            wrapper.eq("CONTEXTSECRET_CODE", relation);
        }

        DynaBean systemFuncRelationBean = metaService.selectOne("JE_RBAC_CONTEXTSECRET", wrapper);
        if (systemFuncRelationBean == null) {
            return null;
        }

        List<DynaBean> systemFuncRelationInfoList = metaService.select("JE_RBAC_SYSFLOWSECRET", ConditionsWrapper.builder()
                .eq("JE_RBAC_CONTEXTSECRET_ID", systemFuncRelationBean.getStr("JE_RBAC_CONTEXTSECRET_ID"))
                .eq("SYSFUNCSECRET_SYSSECRET_CODE", systemSecretCode));
        if (systemFuncRelationInfoList == null || systemFuncRelationInfoList.isEmpty()) {
            return null;
        }

        List<String> codeList = Splitter.on(",").splitToList(systemFuncRelationInfoList.get(0).getStr("SYSFLOWSECRET_FLOWSECRET_CODE"));
        List<String> nameList = Splitter.on(",").splitToList(systemFuncRelationInfoList.get(0).getStr("SYSFLOWSECRET_FLOWSECRET_NAME"));

        JSONTreeNode eachNode;
        for (int i = 0; i < codeList.size(); i++) {
            eachNode = new JSONTreeNode();
            eachNode.setId(codeList.get(i));
            eachNode.setCode(codeList.get(i));
            eachNode.setText(nameList.get(i));
            eachNode.setParent(rootNode.getId());
            eachNode.setNodeType("LEAF");
            eachNode.setLeaf(true);
            eachNode.setLayer("1");
            rootNode.getChildren().add(eachNode);
        }

        return rootNode;
    }

    @Override
    public JSONTreeNode requireDataAttachmentSecretInfo(String relation, String dataSecretCode) {
        JSONTreeNode rootNode = TreeUtil.buildRootNode();

        ConditionsWrapper wrapper = ConditionsWrapper.builder().eq("CONTEXTSECRET_TYPE", "DATACONTEXT");
        if (Strings.isNullOrEmpty(relation)) {
            wrapper.eq("CONTEXTSECRET_DEFAULT_CODE", "1");
        } else {
            wrapper.eq("CONTEXTSECRET_CODE", relation);
        }

        DynaBean dataAttachmentRelationBean = metaService.selectOne("JE_RBAC_CONTEXTSECRET", wrapper);
        if (dataAttachmentRelationBean == null) {
            return null;
        }

        List<DynaBean> dataAttachmentRelationInfoList = metaService.select("JE_RBAC_DATAATTACHSECRET", ConditionsWrapper.builder()
                .eq("JE_RBAC_CONTEXTSECRET_ID", dataAttachmentRelationBean.getStr("JE_RBAC_CONTEXTSECRET_ID"))
                .eq("DATAATTACHSECRET_DATA_CODE", dataSecretCode));
        if (dataAttachmentRelationInfoList == null || dataAttachmentRelationInfoList.isEmpty()) {
            return null;
        }

        List<String> codeList = Splitter.on(",").splitToList(dataAttachmentRelationInfoList.get(0).getStr("DATAATTACHSECRET_ATTACH_CODE"));
        List<String> nameList = Splitter.on(",").splitToList(dataAttachmentRelationInfoList.get(0).getStr("DATAATTACHSECRET_ATTACH_NAME"));

        JSONTreeNode eachNode;
        for (int i = 0; i < codeList.size(); i++) {
            eachNode = new JSONTreeNode();
            eachNode.setId(codeList.get(i));
            eachNode.setCode(codeList.get(i));
            eachNode.setText(nameList.get(i));
            eachNode.setParent(rootNode.getId());
            eachNode.setNodeType("LEAF");
            eachNode.setLeaf(true);
            eachNode.setLayer("1");
            rootNode.getChildren().add(eachNode);
        }
        return rootNode;
    }

    @Override
    public List<String> requireContextDataSecretInfo(String contextSecretCode) {
        DynaBean contextDataRelationBean = metaService.selectOne("JE_RBAC_CONTEXTSECRET", ConditionsWrapper.builder()
                .eq("CONTEXTSECRET_DEFAULT_CODE", "1").eq("CONTEXTSECRET_TYPE", "FORMCONTEXT"));
        if (contextDataRelationBean == null) {
            return null;
        }

        List<DynaBean> contextDataRelationInfoList = metaService.select("JE_RBAC_FORMCONTEXTSECRET", ConditionsWrapper.builder()
                .eq("JE_RBAC_CONTEXTSECRET_ID", contextDataRelationBean.getStr("JE_RBAC_CONTEXTSECRET_ID"))
                .eq("FORMCONTEXTSECRET_CONTEXTSECRET_CODE", contextSecretCode));
        if (contextDataRelationInfoList == null || contextDataRelationInfoList.isEmpty()) {
            return null;
        }

        List<String> result = new ArrayList<>();
        for (DynaBean eachBean : contextDataRelationInfoList) {
            result.addAll(Splitter.on(",").splitToList(eachBean.getStr("FORMCONTEXTSECRET_FORMSECRET_CODE")));
        }

        return result;
    }

    @Override
    public List<String> requireDataFlowSecretInfo(String dataSecretCode) {
        DynaBean dataFlowNodeRelationBean = metaService.selectOne("JE_RBAC_CONTEXTSECRET", ConditionsWrapper.builder()
                .eq("CONTEXTSECRET_DEFAULT_CODE", "1").eq("CONTEXTSECRET_TYPE", "FLOWCONTEXT"));
        if (dataFlowNodeRelationBean == null) {
            return null;
        }

        List<DynaBean> dataFlownNodeRelationInfoList = metaService.select("JE_RBAC_DATAFLOWSECRET", ConditionsWrapper.builder()
                .eq("JE_RBAC_CONTEXTSECRET_ID", dataFlowNodeRelationBean.getStr("JE_RBAC_CONTEXTSECRET_ID"))
                .eq("DATAFLOWSECRET_DATA_CODE", dataSecretCode));
        if (dataFlownNodeRelationInfoList == null || dataFlownNodeRelationInfoList.isEmpty()) {
            return null;
        }

        List<String> result = new ArrayList<>();
        for (DynaBean eachBean : dataFlownNodeRelationInfoList) {
            result.addAll(Splitter.on(",").splitToList(eachBean.getStr("DATAFLOWSECRET_FLOW_CODE")));
        }

        return result;
    }

    private void buildUserContext(String accountId, String secretCode, String secretName) {
        Map<String, String> secretInfoMap = new HashMap<>();
        secretInfoMap.put("contextSecretCode_" + accountId, secretCode);
        secretInfoMap.put("contextSecretName_" + accountId, secretName);
        GlobalExtendedContext.putAll(secretInfoMap);
        secretSettingCache.putMapCache(secretInfoMap);
    }

    private Map<String, String> buildUserContextSecretResult(String accountId, String secretCode, String secretName) {
        Map<String, String> secretInfoMap = new HashMap<>();
        secretInfoMap.put("contextSecretCode", secretCode);
        secretInfoMap.put("contextSecretName", secretName);
        return secretInfoMap;
    }


}
